home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 4 / QRZ Ham Radio Callsign Database - Volume 4.iso / files / amiga / csrc720j.lzh / fbbfwd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-07-05  |  14.2 KB  |  524 lines

  1. /* fbbfwd.c */
  2. /* Copyright P. Hardie VE5VA 1993 */
  3. #include "mb.h"
  4.  
  5. /* Once the compression code is done, the program will have to force
  6.    transparent mode on. The option letter C allows or disallows FBB
  7.    compression (and therefore prevents use of transparent mode if, for
  8.    some reason, it doesn't work.
  9. */
  10.  
  11. char fbb_direction;  /* Tells us whether we called or were called. */
  12. extern char optflags[];
  13. /* From mbfwd */
  14. #define fw_tiout   0x0010  /* Forward timeout flag                       */
  15. extern word  fopts;               /* Options, see defines above.         */
  16. extern char  path[80];            /* "G" item saved here, for logging    */
  17. extern char  fcall[10];           /* Call of the MailBox to forward to   */
  18. /* From mbmail */
  19. #define ln_hier 64
  20. extern int hasbid, needbid, holdit;
  21. extern char fbb_flag;
  22.  
  23. char *proposal = 0;
  24. short lastmsg,fbb_empty = 0;
  25. short msg_nr[10][2];
  26. extern char tmpstr[];
  27.  
  28. fbbfwd(recno)
  29. int recno;
  30. {
  31.    lastmsg = recno;
  32.    fbb_empty = 0;
  33.    if((proposal = malloc(80*20L)) == 0) {
  34.       ttputs("Can't get memory for FBB forwarding\n");
  35.       return;
  36.    }
  37. #ifdef MCH_ZOO
  38.    if(s_mart & zoook) {
  39.       if(zoo_alloc()) {
  40.          ttputs("Can't malloc enough space for ZOO transfer\n");
  41.          return;
  42.       }
  43.    }
  44.    else
  45. #endif
  46.    if(s_mart & cmpok) {
  47.       if(fbb_alloc()) {
  48.          ttputs("Can't malloc enough space for FBB transfer\n");
  49.          return;
  50.       }
  51.    }
  52.    log ('M', 'F', 'S', "");
  53.    if(fbb_direction)goto rcv;
  54.  
  55. /* If compression is on and allowed and we're not already transparent,
  56.    then force transparent mode.
  57.    This is deliberately placed here and in rcv_fbb because forcing into
  58.    command mode while the other end is sending the proposal immediately
  59.    after its SID (because it connected to me) can cause loss of characters.
  60.    The real problem is that you can miss the proposal altogether (if it was
  61.    just FF) and then hang there waiting for a reply which won't come.
  62. */
  63.    if((s_mart & (cmpok | zoook)) && !(port->flags&p_trans)) {
  64.       cmdtnc();
  65.       trantnc();
  66.    }
  67.    while(1) {
  68.       /* Sends a proposal, gets reply, and sends messages if any */
  69.       if(sndfbb())break;
  70. rcv:
  71.       /* Receives a proposal, sends reply, and receives messages if any */
  72.       if(rcvfbb())break;
  73.    }
  74.    free(proposal);
  75. #ifdef MCH_ZOO
  76.    zoo_free();
  77. #endif
  78.    fbb_free();
  79.    log ('M', 'F', 'E', "");
  80.    return;
  81. }
  82.  
  83. /* rcv the fbb proposal and act on it */
  84. rcvfbb()
  85. {
  86.    register int i,j;
  87.    register char *p,*q;
  88.    char c;
  89.    char *prop[20];
  90.    char fbbreply[15];
  91.    int propsum;
  92.  
  93.    propsum = 0;
  94.    i = 0;
  95.    p = proposal;
  96.    while(1) {
  97.       port->line[0]=0;
  98.       getdat();
  99.       if((port->mode & gone) || (port->line[0] != 'F')) {
  100.          fbb_release(0);
  101.          return(1);
  102.       }
  103.       /* Release any previously sent messages.
  104.          Unfortunately this can clobber port->line so it has to be
  105.          temporarily saved from harm.
  106.       */
  107.       strcpy(tmpstr,port->line);
  108.       fbb_release(1);
  109.       strcpy(port->line,tmpstr);
  110.       c = port->line[1];
  111.       if(c == 'F') {
  112.          fbb_empty = 1;
  113.          return(0);
  114.       }
  115.       if(c == '>')break;
  116.       if(c == 'Q') {
  117.          return(1);
  118.       }
  119.       if((!(s_mart&(cmpok|zoook)) && (c == 'B')) ||
  120.                             ((s_mart&(cmpok|zoook)) && (c == 'A'))) {
  121.          prop[i] = p;
  122.          strcpy(p,port->line);
  123.          while(*p && (*p != '\n')) {
  124.             propsum += *p;
  125.             p++;
  126.          }
  127.          /* Add a CR to checksum instead of LF
  128.          */
  129.          propsum += '\r';
  130.          if(*p) *p++ = 0;
  131.          else p++;
  132.          i++;
  133.          continue;
  134.       }
  135.  
  136.       sprintf(tmpstr,"Unknown FBB command %02x '%s'\n",*port->line,port->line);
  137.       ttputs(tmpstr);
  138.       return(2);
  139.    }
  140. /*
  141.    This correctly computes the checksum which is sent after a proposal in
  142.    compressed mode.
  143. printf("propsum = %02x -> %02x\n",propsum&0xff,(-propsum)&0xff);
  144. */
  145.    /* We get here only if a F> has been received. So 'i' better not be zero */
  146.    if(i == 0) {
  147.       ttputs("FBB error: F> was not preceded by proposals\n");
  148.       return(3);
  149.    }
  150. /*
  151.    If compression is on then check the checksum if it is there.
  152.    If we're not already transparent, then force transparent mode.
  153. */
  154.    if(s_mart & (cmpok|zoook)) {
  155.       if((j = fromhex(&port->line[2])) >= 0) {
  156.          propsum += j;
  157.          if(propsum & 0xff) {
  158.             outstr("*** Protocol error - F> Checksum\n");
  159.             return(1);
  160.          }
  161.       }
  162.       if(!port->flags&p_trans) {
  163.          cmdtnc();
  164.          trantnc();
  165.       }
  166.    }
  167.    /* Now go through the proposal list and make up an FS reply */
  168.    strcpy(fbbreply,"FS ");
  169.    q = &fbbreply[3];
  170.    for(j=0;j<i;j++) {
  171.       fbb_parse(prop[j]);
  172.  
  173.       if(fbb_test()) {
  174.          *q++ = '-';
  175.          prop[j] = 0;
  176.       }
  177.       else {
  178.          *q++ = '+';
  179.       }
  180.    }
  181.    *q++ = '\n';
  182.    *q = 0;
  183. ttputs("*");
  184.    outstr(fbbreply);
  185.    /*
  186.       Now read the message(s).
  187.    */
  188.    for(j=0;j<i;j++) {
  189.       if(prop[j] == 0)continue;
  190.       /* Receive this message */
  191.       initmsg(true);
  192.       /* Parse the field again, but this time for real */
  193.       fbb_parse(prop[j]);
  194.       replace_bbs();
  195.       if(port->mmhs->ext != 2)port->mmhs->ext = 0;
  196.       dodis();
  197.       if(port->mmhs->type == 'B')port->mmhs->lifetime = tstaleb;
  198.       else port->mmhs->lifetime = 0;
  199.       if(!(s_mart & (cmpok|zoook)))get_title();
  200.       msgfile(port->cmd,mfhs->next_msg);
  201.       if(s_mart & (cmpok|zoook)) {
  202.          if(rcv_yapp(port->cmd))return(1);
  203.       }
  204.       else {
  205.          if(!uloadm(port->cmd))return(1);
  206.       }
  207.       cremsg();   /* This writes the log record */
  208.    }
  209.    return(0);
  210. }
  211. sndfbb()
  212. {
  213.    register int i,j;
  214.    int extnr;
  215.    register PORTS *p;
  216.    register char *q;
  217.    short msgnr;
  218.    char fbbreply[15];
  219.    unsigned int fbb_size;
  220.  
  221.    /* Clear the msg proposal area */
  222.    for(i=0;i<5;i++)msg_nr[i][0] = 0;
  223.    fbb_size;
  224.    p = port;
  225.    if(lastmsg == 0) {
  226. ttputs("*");
  227.       if(fbb_empty) {
  228.          outstr("FQ\n");
  229.          return(1);
  230.       }
  231.       outstr("FF\n");
  232.       return(0);
  233.    }
  234.    i = 0;
  235.    j = 0;
  236.    for(;lastmsg > 0;lastmsg--) {
  237.       read_rec(mfl, lastmsg, (char *)p->mmhs);
  238.       if((extnr = check_ok()) == 0)continue;
  239.       p->mmhs->stat setbit m_busy;
  240.       wt_mmhs();
  241.       /* Store info about current message and send proposal */
  242.       if(extnr > 0)extnr -= 1;
  243.       msg_nr[i][0] = lastmsg;
  244.       msg_nr[i][1] = extnr;
  245.       fbb_flag = 1;
  246.       if(s_mart & (cmpok|zoook)) {
  247.          if((s_mart&hidok)and(p->mmhs->ext is 2))
  248.             prtx("FA $B $P $h $G $b $s");
  249.          else
  250.             prtx("FA $B $P $A $G $b $s");
  251.       }
  252.       else {
  253.          if((s_mart&hidok)and(p->mmhs->ext is 2))
  254.             prtx("FB $B $P $h $G $b $s");
  255.          else
  256.             prtx("FB $B $P $A $G $b $s");
  257.       }
  258.       fbb_size += p->mmhs->size;
  259.       fbb_flag = 0;
  260.       /* Compute the checksum.
  261.          It's best not to put the \n in the prtx string because, with
  262.          fbb_flag on, prtx maps \n into \r\n
  263.       */
  264.       for(q=tmpstr;*q;q++) {
  265.          j += *q;
  266.       }
  267.       j += '\r';
  268. ttputs("*");
  269.       outstr(tmpstr);
  270.       outchar('\n');
  271.       i++;
  272.       if((i == 5) || (fbb_size > 10000)) {
  273.          /* Count this last message because breaking from the loop would
  274.             avoid it
  275.          */
  276.          lastmsg--;
  277.          break;
  278.       }
  279.    }
  280.    if(i == 0) {
  281. ttputs("*");
  282.       outstr("FF\n");
  283.       return(0);
  284.    }
  285. ttputs("*");
  286.    if(s_mart & (cmpok|zoook)) {
  287.       sprintf(tmpstr,"F> %02x\n",(-j)&0xff);
  288.       tmpstr[3] = toupper(tmpstr[3]);
  289.       tmpstr[4] = toupper(tmpstr[4]);
  290.       outstr(tmpstr);
  291.    }
  292.    else {
  293.       outstr("F>\n");
  294.    }
  295.    /* Now get their answer and see if they want any of them */
  296.    getdat();
  297.    if(p->mode & gone) {
  298. release:
  299.       fbb_release(0);
  300.       return(1);
  301.    }
  302.    if((port->line[1] != 'S') || (port->line[2] != ' ')) {
  303.       if(port->line[0] == '*') {
  304.          ttputs("FBB error from remote end or disconnect\n");
  305.       }
  306.       else {
  307.          ttputs("Invalid FS reply!\n");
  308.       }
  309.       goto release;
  310.    }
  311.    strncpy(fbbreply,port->line,14);
  312.    /*
  313.       The FBB forwarding is now done in three stages.
  314.       1. Make sure that the number of replies on the FS line is exactly
  315.          the same as the number of proposals that we sent. If they are
  316.          not we can't be sure which message any of them refers to.
  317.       2. Go through the replies and release messages which are deferred
  318.          (=), and mark as forwarded then release those which are rejected
  319.          (-).
  320.       3. Go through the replies again and this time send those messages
  321.          which were accepted (+).
  322.       The reason for this process is that first of all we can't proceed
  323.       unless the FS reply appears to be valid. Secondly, if the link drops
  324.       during transfer of messages it doesn't change the fact that messages
  325.       which were rejected should be marked as such and the deferred ones
  326.       don't matter anyway. But if the link drops, all messages which
  327.       were accepted should NOT be marked as forwarded.
  328.       Note that when this routine finishes sending the requested messages,
  329.       it doesn't mark them. That is done at the beginning of the rcvfbb
  330.       routine after it has received a valid prompt of some sort from the
  331.       other end. Otherwise it doesn't mark the messages and it aborts the
  332.       connection.
  333.       So, here we go.
  334.    */
  335.  
  336.    /* 1.
  337.       Make sure the number of replies in the FS line equals the number
  338.       of proposals that we sent
  339.    */
  340.    q = &fbbreply[3];
  341.    for(j=0;j<5;j++,q++) {
  342.       if(*q == '-')continue;
  343.       if(*q == '=')continue;
  344.       if(*q == '+')continue;
  345.       break;
  346.    }
  347.    if(j != i) {
  348.       outstr("*** Protocol error in FS\n");
  349.       goto release;
  350.    }
  351.  
  352.    /* 2.
  353.       Before doing the forwarding, remove those that are refused or deferred
  354.       There's no point waiting until the prompt after I've sent the files
  355.       that need to be sent because if the link dies, it doesn't change the
  356.       fact that they don't want these messages.
  357.    */
  358.    q = &fbbreply[3];
  359.    for(j=0;j<i;j++,q++) {
  360.       if(*q == '-') {
  361.          /* They've already go it.
  362.          */
  363.  
  364.          read_rec(mfl, msg_nr[j][0], (char *)p->mmhs);
  365.          markdis(msg_nr[j][1]);  /*extnr*/
  366.          p->mmhs->stat clrbit m_busy;
  367.          if (p->mmhs->ext isnt 1) {
  368.             pcall(p->mmhs->fwdc, fcall);
  369.             p->mmhs->fport = p->id;
  370.          }
  371.          write_rec(mfl, p->mmhs->rn, (char *)p->mmhs);
  372.          makehdr2();
  373.          sprintf(p->line, "%u %s", p->mmhs->number, path);
  374.          log ('M', 'F', ' ', p->line);
  375.          msg_nr[j][0] = 0;
  376.          continue;
  377.       }
  378.       if(*q == '=') {
  379.          /* Deferred ... maybe send it later */
  380.  
  381.          read_rec(mfl, msg_nr[j][0], (char *)p->mmhs);
  382.          p->mmhs->stat clrbit m_busy;
  383.          write_rec(mfl, p->mmhs->rn, (char *)p->mmhs);
  384.          msg_nr[j][0] = 0;
  385.          continue;
  386.       }
  387.    }
  388.  
  389.    /* 3.
  390.       Now do the actual forwarding if there are any left
  391.    */
  392.    q = &fbbreply[3];
  393.    for(j=0;j<i;j++,q++) {
  394.       if(*q != '+') continue;
  395.       /* Handle the case where they want the message .. .send it and
  396.          mark it as sent
  397.       */
  398.       read_rec(mfl, msg_nr[j][0], (char *)p->mmhs);
  399.       if(s_mart & (cmpok|zoook)) {
  400.          /* Compressed protocol uses YAPP. */
  401.          /* snd_yapp returns zero on success */
  402.          if(snd_yapp()) {
  403.             fopts setbit fw_tiout;
  404.             /* Release this one now since it's already in memory */
  405.             p->mmhs->stat clrbit m_busy;
  406.             write_rec(mfl, msg_nr[j][0], (char *)p->mmhs);
  407.             msg_nr[j][0] = 0;
  408.             goto release;
  409.          }
  410.       }
  411.       else {
  412.          /* Otherwise use ASCII protocol */
  413.          outstr(p->mmhs->title);
  414.          outchar('\n');
  415.          curtim();
  416.          prtx(mm[4]);
  417.          /* xmtmsg returns 1 on succes */
  418.          if(!xmtmsg()) {
  419.             fopts setbit fw_tiout;
  420.             /* Release this one now since it's already in memory */
  421.             p->mmhs->stat clrbit m_busy;
  422.             write_rec(mfl, msg_nr[j][0], (char *)p->mmhs);
  423.             msg_nr[j][0] = 0;
  424.             goto release;
  425.          }
  426.       }
  427.    }
  428.    return(0);
  429. }
  430.  
  431. /*
  432.    Release those messages whose record numbers remain in msg_nr[*][0].
  433.    If mark is non_zero then mark them as forwarded, otherwise simply
  434.    remove the busy bit and release the record.
  435. */
  436. fbb_release(mark)
  437. int mark;
  438. {
  439.    register int i;
  440.    register PORTS *p;
  441.  
  442.    p = port;
  443.    for(i=0;i<5;i++) {
  444.       if(msg_nr[i][0]) {
  445.          read_rec(mfl, msg_nr[i][0], (char *)p->mmhs);
  446.          p->mmhs->stat clrbit m_busy;
  447.          if(mark) {
  448.             markdis(msg_nr[i][1]);  /*extnr*/
  449.             if (p->mmhs->ext isnt 1) {
  450.                pcall(p->mmhs->fwdc, fcall);
  451.                p->mmhs->fport = p->id;
  452.             }
  453.          }
  454.          write_rec(mfl, msg_nr[i][0], (char *)p->mmhs);
  455.          if(mark) {
  456.             makehdr2();
  457.             sprintf(p->line, "%u %s", p->mmhs->number, path);
  458.             log ('M', 'F', ' ', p->line);
  459.          }
  460.       }
  461.    }
  462. }
  463. /* Put all the fields of an FBB proposal into the port->mmhs structure */
  464. fbb_parse(pp)
  465. char *pp;
  466. {
  467.    register char *p,*q;
  468.    register char *qq;
  469.  
  470.    p = pp;
  471.    fill(port->mmhs->fwdc, '\0', ln_call);
  472.    port->mmhs->type = p[3];
  473.    /* Next two are only required so that the correct info will be logged */
  474.    port->opt1 = 'S';
  475.    port->opt2 = p[3];
  476.    p += 5;
  477.    ljsf(port->mmhs->from,p,ln_call);
  478.    while(*p != ' ')p++;
  479.    p++;
  480.    pcall(port->mmhs->bbs, p);
  481.    port->mmhs->ext = 0;
  482.    /* If there's no period in the string or the period occurs after the
  483.       space which follows the BBS, then it's not a hierarchical call.
  484.       In this case it is looked up in states.mb by chkhier()
  485.  
  486.       Otherwise, the hierarchical call is stored.
  487.    */
  488.    if(((qq = strchr(p, '.')) is NULL) || (qq > strchr(p,' '))) {
  489.       chkhier();
  490.    }
  491.    else {
  492.       port->mmhs->ext = 2;
  493.       fill(port->mmhs->call, '\0', 124);
  494.       q = (char *)port->mmhs->call;
  495.       while(*p != ' ')*q++ = *p++;
  496.    }
  497.    while(*p != ' ')p++;
  498.    p++;
  499.    ljsf(port->mmhs->to,p,ln_call);
  500.    while(*p != ' ')p++;
  501.    p++;
  502.    ljsf(port->mmhs->bid,p,ln_bid);
  503.    while(*p != ' ')p++;
  504.    p++;
  505.    port->mmhs->size = atoi(p);
  506.    hasbid = 1;
  507. }
  508. /* After a fbb_parse(), test to see if we want this message */
  509. fbb_test()
  510. {
  511.    if(test_reject())return(1);
  512.    if(test_bbs()) {
  513.       /* If it's an unknown @BBS in a bulletin and my option is active,
  514.          reject the bulletin.
  515.       */
  516.       if(optflags[0] && (port->mmhs->type == 'B')) {
  517.          return(1);
  518.       }
  519.    }
  520.    checkbid();
  521.    if(!needbid)return(1);
  522.    return(0);
  523. }
  524.